Acoustic scene classification

When interacting with mobile devices we expect relevant information to be presented with a minimum of input effort. What is relevant depends on the context in which we are acting.

If we are requesting a route information while sitting at a busstop we most probably are looking for directions for travel via a bus, while at a railway station we most probably are looking for a train connection.

One possibility for a device to identify the context is via geolocation information. But this information is may not be available inside buildings. An alternative approach is the analysis of ambient noise. This approach is referred to by the term acoustic scene classification.

Acoustic scene classification (ACS) describes the "capability of a human or anartificial system to understand an audio context, either from an on-linestream or from a recording." (http://www.cs.tut.fi/sgn/arg/dcase2016/documents/workshop/Valenti-DCASE2016workshop.pdf).

This workbook demonstrates how convolutional networks can be used for the classification.

We will be applying a pre-trained VGG-16 network with custom classifier applied on log-frequency power spectrograms.

Data analysis and preparation

This project uses recordings made available as part of the DCASE (Detection and Classification of Acoustic Scenes and Events) 2019 challenge (http://dcase.community/challenge2019/task-acoustic-scene-classification). The TAU Urban Acoustic Scenes 2019 development dataset contains recordings in 10 different settings (airport, indoor shopping mall, metro station, pedestrian street, stree traffic, tram, bus, metro, park) recorded in 10 cities. Each recording is 10 seconds long. The data files can be downloaded from https://zenodo.org/record/2589280 using data/download.sh.

This workbook assumes that the extracted audio files are in directory data/TAU-urban-acoustic-scenes-2019-development/audio/ relative to this notebook.

In [1]:
import IPython.display as ipd
import librosa, librosa.display
import math
import numpy as np
from collections import OrderedDict
import os
from PIL import Image, ImageDraw, ImageOps
import pandas as pd
import matplotlib.pyplot as plt
import random
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import MinMaxScaler
import torch
from torch import nn, optim
from torchvision import datasets, transforms, models
import warnings
import wave

Let's analyze what the data looks like:

In [2]:
rawDataPath = 'data/TAU-urban-acoustic-scenes-2019-development/audio/'

def filenames2dataFrame(path):
    """Collect metadata of audio files
    
    path   - directory containing audio files
    return - data frame with metadata
    """
    
    data = []
    for filename in os.listdir(path):
        filepath = os.path.join(path, filename)
        head, tail = os.path.split(filename)
        parts = tail.split('-', 2)
        with wave.open(filepath, "rb") as file:
            sr = file.getframerate()
            duration = file.getnframes() / sr
        data.append( {
            'setting' : parts[0],
            'city' : parts[1],
            'recording' : parts[2],
            'duration' : duration,
            'sr' : sr
        })
    return pd.DataFrame(data)

df = filenames2dataFrame(rawDataPath)

print('Durations are in the range {} - {} s.\n'.format(df['duration'].min(), df['duration'].max()))
print('Sample rates are in the range {} - {} Hz.\n'.format(df['sr'].min(), df['sr'].max()))
print('There are a total of {} recordings.\n'.format(df.shape[0]))
print('Number of recordings per category:\n')
print(df.set_index(['setting', 'city', 'duration', 'sr']).count(level='setting'))
print(df.set_index(['setting', 'city', 'duration', 'sr']).count(level='city'))
Durations are in the range 9.999979166666666 - 10.000020833333334 s.

Sample rates are in the range 48000 - 48000 Hz.

There are a total of 14400 recordings.

Number of recordings per category:

                   recording
setting                     
airport                 1440
bus                     1440
metro                   1440
metro_station           1440
park                    1440
public_square           1440
shopping_mall           1440
street_pedestrian       1440
street_traffic          1440
tram                    1440
           recording
city                
barcelona       1421
helsinki        1447
lisbon          1440
london          1444
lyon            1440
milan           1440
paris           1452
prague          1440
stockholm       1456
vienna          1420

This looks benign:

  • For each setting we have the same number of recordings.
  • All recordings are roughly of same duration.
  • All recordings use the same sample rate.

Let's listen to one of the files.

In [3]:
sr = 48000

def readAudioFile(filename, sr=48000):
    """Reads an audio file with default sampling rate 48000Hz
    
    filename - file to be read
    return - numpy.float32
    """
    x, sr = librosa.load(filename, sr=sr)
    return x
In [4]:
x = readAudioFile(rawDataPath + 'street_pedestrian-lyon-1162-44650-a.wav')
print('number of samples {}'.format(x.shape[0]))
ipd.Audio(x, rate=sr)
number of samples 479999
Out[4]:

Spectrograms

To analyze the audio files we can transform them into spectrograms (cf. https://en.wikipedia.org/wiki/Spectrogram). These show the frequency distribution for subsequent short time intervals.

Mel spectrograms

A popular form of spectrograms are Mel spectrograms. The Mel scale is based on what humans perceive as equal pitch differences. The Mel scale defines how the frequency axis is scaled:

$$m = 2595 \log_{10}\left(1 + \frac{f}{700}\right)$$

The result of the scaling is that for high frequencies the scale is proportional to the logarithm of the frequency while low frequency (especially below 700 Hz) are compressed.

For speech analysis this scale is widely used.

In [5]:
def melSpectrogram(x, sr=48000):
    """Draw mel spectrogram
    
    x  - samples
    sr - sample rate
    """
    
    hop_length = 1875 # This gives us 256 time buckets: 1875 = 10 * 48000 / 256
    n_fft = 8192 # This sets the lower frequency cut off to 48000 Hz / 8192 * 2 = 12 Hz
    S = librosa.feature.melspectrogram(x, sr=sr, n_fft=n_fft, hop_length=hop_length)
    logS = librosa.power_to_db(abs(S))
    plt.figure(figsize=(15, 5))
    librosa.display.specshow(logS, sr=sr, hop_length=hop_length, x_axis='time', y_axis='mel')
    plt.colorbar(format='%+2.0f dB')
    plt.title('Mel power spectrum')
    
melSpectrogram(x)
  • Most of the audio power is concentrated on low frequencies.
  • A lot of the structure that we can see is in the low frequencies.
  • High frequencies seem to be filtered out.

Ambiant sound can contain a lot of low frequency sounds, e.g.

  • Automobile motors run at 600 - 6000 rpm. With four cylinders that results in a 40 - 400 Hz exhaust frequency.
  • Ventilators typically run at 750 - 3000 rpm.

These are the frequencies that are compressed by the Mel scale.

When the running speed of machines is changed this will move much of the sound spectrum by the same factor. While the Mel scale distorts this shift for low frequencies the spectrum would be simply translated along the frequency axis on a pure logarithimic scale by the same distance.

So using a logarithmic scale for the the analysis seems more appropriate.

Let's create a log-frequency power spectrogram (also referred to as constant-Q power spectrogram).

Log-frequency spectrograms

In [6]:
def logFrequencySpectrogram(x, sr=48000):

    hop_length = 1024 # must be a multiple of 2^number_of_octaves
    n_bins = 256 # number of bins
    bins_per_octave = 24 # a quarter note
    fmin = 10 # 10 Hz
    fmax = fmin * math.pow(2., n_bins / bins_per_octave)
    C = librosa.cqt(x, sr=sr, fmin = 10, hop_length=hop_length, n_bins= n_bins,
                    bins_per_octave = bins_per_octave)
    logC = librosa.power_to_db(np.abs(C))
    return logC

def drawLogFrequencySpectrogram(x, sr=48000):
    logC = logFrequencySpectrogram(x, sr)
    plt.figure(figsize=(15, 5))
    librosa.display.specshow(logC, sr=sr, x_axis='time', y_axis='cqt_hz', fmin = 10, bins_per_octave = 24)
    plt.colorbar(format='%+2.0f dB')
    plt.title('Constant-Q power spectrum')
    plt.show()
In [7]:
drawLogFrequencySpectrogram(x)
  • With the log-frequency spectrogram the structure fo low the frequency noise is clearly visible.
  • The audio power is more distributed over the frequency intervals.
  • Yet high frequencies are still underrepresented.

Pre-emphasis

The high frequency can be emphasized using a filter.

In [8]:
def preEmphasis(x, alpha=.97):
    """emphasise high frequencies
    
    This filter mixes the signal with its first derivative:
    
    y[n] = (x[n] - alpha * x[n-1]) / (1 - alpha)

    Reference:
    Haytham Fayek,
    "Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral
    Coefficients (MFCCs) and What's In-Between",
    https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html
    
    The implementation by Haytham Fayek lacks a good first value. This
    implementation uses x[-1] = 2 * x[0] - x[1].
    Further to keep the amplitudes for low frequencies unchanged the output signal
    is divided by (1 - alpha).

    x - original signal
    alpha - proportion of the output signal that comes from the first derivative
    """
    return np.append((1 - 2 * alpha) * x[0] + alpha * x[1],
                     x[1:] - alpha * x[:-1]) / (1 - alpha)

p = preEmphasis(x, .97)
ipd.Audio(p, rate=sr)
Out[8]:
In [9]:
drawLogFrequencySpectrogram(p)

The spectogram can easily be converted to a black and white image.

In [10]:
def bwLogFrequencySpectrogram(x, sr=48000):
    """Create a log-requency spectrogram as an image
    
    x      - samples
    return - spectrogram
    """
    logC = logFrequencySpectrogram(p);
    scaler = MinMaxScaler(feature_range=(0, 255))
    logC = scaler.fit_transform(logC)
    img = Image.fromarray(logC)
    img = img.transpose(Image.FLIP_TOP_BOTTOM)
    return img

def drawImage(img):
    plt.figure(figsize=(12, 7))
    plt.imshow(img, cmap=plt.cm.gray)
        

drawImage(bwLogFrequencySpectrogram(p))

The accompanying script convert.py can be used to convert all recordings to spectrograms

data/TAU-urban-acoustic-scenes-2019-development/audio/ data/spectrograms/

The script saves the data in directory structure like

|- airport
||- barcelona
||- helsinki
|...
|- bus
||- barcelona
||- helsinki
...

In the following it is assumed that the spectrograms are available in directory data/spectrograms relative to this notebook.

In [11]:
# Let's check
img = Image.open('data/spectrograms/street_pedestrian/lyon/1162-44650-a.png')
drawImage(img)
# You should see the same image as above

Modelling

Data augmentation

The number of recordings per category are rather small. To avoid overfitting data augmentation should be applied.

For image data a large variety of transformtions can be used for augmentation. These include for instance random resized cropping, rotations, and flipping (see for instance https://github.com/aleju/imgaug).

Not all make sense for spectrograms,eg. rotations. Reasonable transformations are:

In [12]:
class RandomAudioTransform:
    """Randomly transform short time spectrogram

    The spectrogram is transformed randomly in three ways:

    * The spectrogram frequencies are transposed randomly.
    * The tempo is randomly changed.
    * A random sampling window in time is chosen.

    size             - target image size of the spectrogram
    octaves          - number of octaves by which to shift spectrogram
    bins_per_octaves - number of image pixels per octave
    dilation         - maximum relative increment of the tempo
    sample_size      - size of the time window in relation to the whole
                       spectrogram
    random           - True: use random values, False: replace random values by
                       fixed values
    """

    def __init__(self, size=224, octaves=.5, bins_per_octave=24, dilation=0.25,
                 sample_size=.5, random=True):
        """Construct new RandomAudioTransform
        """

        self.size = size
        self.octaves = octaves
        self.bins_per_octave = bins_per_octave
        self.dilation = dilation
        self.sample_size = sample_size
        self.random = random

    def rand(self):
        """Generate random number from interval [0., 1.[
        """

        if self.random:
            return random.random()
        return .5

    def __call__(self, img):
        """Transform a spectrogram provided as image

        img    - image to transform
        Return - transformed image
        """

        # Stretch the time axis according sample size and time dilation
        width = int((1. + self.dilation * self.rand())
                    * self.size / self.sample_size)
        img = img.resize(size=[width, img.size[1]], resample=Image.BICUBIC)
        # Take sample from image
        alpha = self.octaves * self.bins_per_octave / (img.size[0] - self.size)
        center = [self.rand(), (1 - alpha) * .5 + alpha * self.rand()]
        img = ImageOps.fit(img, size=[self.size, self.size],
                           method=Image.BICUBIC, centering=center)
        return img
In [13]:
# By default a random 5 second sample of the spectrogram shifted by up to .5 octavs is created.
# Just reexecute this cell to see the random changes.
transform = RandomAudioTransform()
img = Image.open('data/spectrograms/street_pedestrian/lyon/1162-44650-a.png')
drawImage(transform(img))
pass

In "SpecAugment: A Simple Augmentation Method for Automatic Speech Recognition", 2019, Zoph et.al suggest masking frequency bands for augmentation (https://ai.google/research/pubs/pub48482/, https://arxiv.org/pdf/1904.08779.pdf).

In [14]:
class FrequencyMask:
    """Randomly mask frequency band in short time spectrogram

    The spectrogram is transformed randomly in three ways:

    * The spectrogram frequencies are transposed randomly.
    * The speed is randomly changed.
    * A random sampling window in time is chosen.

    max_width        - maximum portion of all frequencies that will be masked
    """

    def __init__(self, max_width = .2):
        """Construct new FrequencyMask
        """

        self.max_width = max_width

    def __call__(self, img):
        """Transform a spectrogram provided as as image

        img    - image to transform
        Return - transformed image
        """
        width, height = img.size
        mask_height = height * self.max_width * random.random()
        ymin = math.floor((height - mask_height) * random.random())
        ymax = math.floor(mask_height + ymin)
        draw = ImageDraw.Draw(img)
        draw.rectangle(((0, ymin), (width - 1, ymax)), fill=(127, 127, 127))
        return img
In [15]:
# A random frequency band is masked.
# Just reexecute this cell to see the random changes.
transform = FrequencyMask()
img = Image.open('data/spectrograms/street_pedestrian/lyon/1162-44650-a.png')
drawImage(transform(img))
pass

Train, validation, and test data sets

In machine learning we should use separate data sets for training, validation and testing. Accompanying script split.py is provided for executing the split with using a 80:20:20 ratio on each setting-city combination:

python3 ./split.py data/spectrograms data/splitted

In the following it is assumed that the splitted data set is available in data/splitted.

In [16]:
# Let's check (assuming Linux as operating system). The result should be close to 8640, 2880, 2880
print("train: {}".format(os.popen("find data/splitted/train -name '*.png' | wc -l").read()))
print("valid: {}".format(os.popen("find data/splitted/valid -name '*.png' | wc -l").read()))
print("test: {}".format(os.popen("find data/splitted/test -name '*.png' | wc -l").read()))
train: 8601

valid: 2901

test: 2898

Neural network training

Using a pre-trained network as starting point very much simplifies finding good solutions. One example of a pre-tained network for image recognition is VGG16 (Karen Simonyan, Andrew Zisserman, "Very Deep Convolutional Networks for Large-Scale Image Recognition", 2014, https://arxiv.org/abs/1409.1556) delivered with the torchvision package.

I have tested both VGG16 and VGG19 in this project but found no benefit in using VGG19 which has some additional layers.

Transforms

In [17]:
# This normalization has been used for pre-training the VGG16 model.
transform_norm = transforms.Normalize(
    [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
train_transforms = transforms.Compose([RandomAudioTransform(
    random=True),
                                       FrequencyMask(.2),
                                       transforms.ToTensor(),
                                       transform_norm])

test_transforms = transforms.Compose([RandomAudioTransform(
    random=False),
                                      transforms.ToTensor(),
                                      transform_norm])

Data loaders

In [18]:
data_dir = 'data/splitted'

train_dir = os.path.join(data_dir, 'train')
test_dir = os.path.join(data_dir, 'test')
valid_dir = os.path.join(data_dir, 'valid')

train_data = datasets.ImageFolder(train_dir, transform=train_transforms)
valid_data = datasets.ImageFolder(valid_dir, transform=test_transforms)
test_data = datasets.ImageFolder(test_dir, transform=test_transforms)

class_to_idx = test_data.class_to_idx

# The batch sizes below fit into the 6GB of an Nvidia GTX 1060.
trainloader = torch.utils.data.DataLoader(
    train_data, batch_size=32, shuffle=True)
validloader = torch.utils.data.DataLoader(
    valid_data, batch_size=32, shuffle=True)
testloader = torch.utils.data.DataLoader(
    test_data, batch_size=32, shuffle=True)

Model

In [19]:
def get_in_features(model):
    """Get the number of in_features of the classifier
    """
    in_features = 0
    for module in model.classifier.modules():
        try:
            in_features = module.in_features
            break
        except AttributeError:
            pass
    return in_features

def create_classifier(model, out_features, hidden_units=512):
    """Create the classifier
    """
    classifier = nn.Sequential(OrderedDict([
        ('fc1', nn.Linear(get_in_features(model), hidden_units)),
        ('relu1', nn.ReLU(inplace=True)),
        ('drop1', nn.Dropout(.5)),
        ('fc2', nn.Linear(hidden_units, hidden_units)),
        ('relu2', nn.ReLU(inplace=True)),
        ('drop2', nn.Dropout(.5)),
        ('fc3', nn.Linear(hidden_units, out_features)),
        ('output', nn.LogSoftmax(dim=1))
    ]))
    model.classifier = classifier
In [20]:
def load_model(classifier_only = True):
    """ Load the pretrained model
    
    classifier_only - change classifier parameters only
    """
    
    method_to_call = getattr(models, 'vgg16')
    model = method_to_call(pretrained=True)

    if classifier_only:
        # Do not update model parameters
        for param in model.parameters():
            param.requires_grad = False

    # Add our own classifier
    create_classifier(model, out_features=len(class_to_idx), hidden_units=512)
    
    return model

model = load_model()
In [21]:
def check_accuracy(model, testloader, device='cuda', print_every=40):
    """Check the accuracy of the model"""
    correct = 0
    total = 0
    steps = 0
    expected = []
    actual = []

    model.to(device)
    model.eval()

    with torch.no_grad():
        for inputs, labels in testloader:
            steps += 1
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            _, predicted = torch.max(outputs.data, 1)

            for label in labels.tolist():
                expected.append(label)
            for prediction in predicted.tolist():
                actual.append(prediction)

            total += labels.size(0)
            correct += (predicted == labels).sum().item()

            print('-', end='', flush=True)
            if steps % print_every == 0:
                print()
    accuracy = 100 * correct / total    
    print('\nAccuracy: {:.4f} %'.format(accuracy))
    print('Confusion matrix')
    print(confusion_matrix(expected, actual))
    return accuracy
In [22]:
def save_checkpoint(path, model, optimizer, class_to_idx):
    """Save a checkpoint"""
    model.class_to_idx = class_to_idx
    warnings.filterwarnings("ignore", category=UserWarning)
    torch.save({'model': model,
                'optimizer': optimizer}, path)
    warnings.filterwarnings("default", category=UserWarning)
In [23]:
def do_deep_learning(model, criterion, optimizer, epochs=1, device='cuda', print_every=40):
    """Execute training steps
    
    Training is discontinued if there is no improvement for 10 epochs.
    
    """

    model.to(device)
    model.train()
    
    best_accuracy = 0.0
    worse_count = 0
    
    for epoch in range(epochs):
        running_loss = 0
        steps = 0
        for inputs, labels in trainloader:
            steps += 1

            inputs, labels = inputs.to(device), labels.to(device)

            optimizer.zero_grad()

            # Forward and backward passes
            outputs = model.forward(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            running_loss += loss.item()

            print('.', end='', flush=True)
            if steps % print_every == 0:
                print("Epoch: {}/{}, ".format(epoch + 1, epochs),
                      "Loss: {:.4f}".format(running_loss/print_every))
                running_loss = 0

        while steps % print_every != 0:
            print(' ', end='')
            steps += 1
        print("Epoch {} completed".format(epoch + 1))
        accuracy = check_accuracy(model, validloader)
        
        if accuracy >= best_accuracy:
            best_accuracy = accuracy
            worse_count = 0
            # To avoid disk wear the checkpoint is saved in the
            # /tmp directory which hopefully is a RAM disk.
            save_checkpoint('/tmp/checkpoint.pt', model, optimizer, class_to_idx)
        else:
            worse_count += 1
            if worse_count == 10:
                print("No improvement for 10 epochs")
                break

    print()            
In [24]:
# To make this reproducible let'use fixed random seeds
torch.manual_seed(8259)
random.seed(6745)

optimizer = optim.Adam(model.classifier.parameters(), lr=.001)
criterion = nn.NLLLoss()
do_deep_learning(model, criterion, optimizer, epochs=200)
........................................Epoch: 1/200,  Loss: 2.3941
........................................Epoch: 1/200,  Loss: 2.0572
........................................Epoch: 1/200,  Loss: 1.8963
........................................Epoch: 1/200,  Loss: 1.8545
........................................Epoch: 1/200,  Loss: 1.8011
........................................Epoch: 1/200,  Loss: 1.7795
.............................           Epoch 1 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 45.1913 %
Confusion matrix
[[  0   2   1   4   3   3 193  85   0   0]
 [  0 278   1   2   1   0   0   2   1   5]
 [  0  85  73  45  19   0  18  13   1  37]
 [  0  27  22  41  16   5 118  34  17  10]
 [  0   6   0   8 242   4   0  11  15   4]
 [  0   2   1  14  51  30  59 104  28   1]
 [  0   1   3  12   0   1 225  48   0   0]
 [  0   3   0   8  21  10 100 138   8   1]
 [  0   7   1  12  27  14   7  31 189   2]
 [  0 112  26  26  17   0   6   8   0  95]]
........................................Epoch: 2/200,  Loss: 1.4425
........................................Epoch: 2/200,  Loss: 1.3861
........................................Epoch: 2/200,  Loss: 1.3980
........................................Epoch: 2/200,  Loss: 1.4177
........................................Epoch: 2/200,  Loss: 1.3284
........................................Epoch: 2/200,  Loss: 1.3401
.............................           Epoch 2 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 50.0517 %
Confusion matrix
[[262   0   2   3   0   3   4  17   0   0]
 [  1 262  11   1   2   0   0   0   2  11]
 [ 25  38 156  18   9   3   2   1   2  37]
 [110  21  38  31   6   6  30  16  23   9]
 [  9   4   2   3 229  12   0   6  19   6]
 [107   0   1   1  24  39   6  72  40   0]
 [208   1   3   7   0   2  46  22   1   0]
 [145   4   2   3  12  11   1 101   8   2]
 [  5   4   2   4  18  20   1  19 215   2]
 [ 14  61  77  16   8   1   0   2   0 111]]
........................................Epoch: 3/200,  Loss: 1.2670
........................................Epoch: 3/200,  Loss: 1.2960
........................................Epoch: 3/200,  Loss: 1.2667
........................................Epoch: 3/200,  Loss: 1.2469
........................................Epoch: 3/200,  Loss: 1.2447
........................................Epoch: 3/200,  Loss: 1.2327
.............................           Epoch 3 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 54.8432 %
Confusion matrix
[[ 31   0   2   7   4  41 100 105   0   1]
 [  0 251  23   3   2   1   0   0   1   9]
 [  0  26 174  22   7  10   5  12   1  34]
 [  5  12  28  80   6  27  53  61   3  15]
 [  0   1   3   2 251  20   0   5   3   5]
 [  3   0   2   4  33 159  23  64   2   0]
 [  7   1   2  10   0  17 198  55   0   0]
 [  3   1   2   4  13  76  23 166   1   0]
 [  0   2   0   6  32  92   0  10 146   2]
 [  1  23  93  14   9   4   0  11   0 135]]
........................................Epoch: 4/200,  Loss: 1.2344
........................................Epoch: 4/200,  Loss: 1.2432
........................................Epoch: 4/200,  Loss: 1.1804
........................................Epoch: 4/200,  Loss: 1.2161
........................................Epoch: 4/200,  Loss: 1.1529
........................................Epoch: 4/200,  Loss: 1.2364
.............................           Epoch 4 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 56.9804 %
Confusion matrix
[[215   1   3  14   0   0  44  14   0   0]
 [  0 247  31   5   2   0   0   1   1   3]
 [ 11  15 201  42   6   0   2   1   1  12]
 [ 35   8  27 155   5   0  41  10   4   5]
 [  4   1   2   5 265   3   0   3   7   0]
 [ 92   1   0  19  43  27  31  67  10   0]
 [ 65   1   2  22   0   0 189  11   0   0]
 [ 79   2   1  21  13   5  62 102   4   0]
 [ 10   1   0  18  42   8   3  26 182   0]
 [  4  23 143  29  14   0   0   7   0  70]]
........................................Epoch: 5/200,  Loss: 1.0633
........................................Epoch: 5/200,  Loss: 1.1644
........................................Epoch: 5/200,  Loss: 1.1438
........................................Epoch: 5/200,  Loss: 1.1290
........................................Epoch: 5/200,  Loss: 1.1742
........................................Epoch: 5/200,  Loss: 1.1560
.............................           Epoch 5 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 58.1524 %
Confusion matrix
[[250   0   1   5   0  12  11  12   0   0]
 [  0 273   5   0   0   0   1   1   1   9]
 [ 27  31 130  26   0   2   4   1   1  69]
 [ 75  13  14  96   1   9  41  16  11  14]
 [  5   3   2  13 167  67   0   8  19   6]
 [ 66   0   1   5   4 127  12  61  12   2]
 [124   0   4   7   0   4 129  22   0   0]
 [ 84   2   0   8   0  36  14 138   4   3]
 [  2   2   0   6   4  52   0  20 201   3]
 [  9  48  24  25   2   2   0   4   0 176]]
........................................Epoch: 6/200,  Loss: 1.1267
........................................Epoch: 6/200,  Loss: 1.0937
........................................Epoch: 6/200,  Loss: 1.1275
........................................Epoch: 6/200,  Loss: 1.0814
........................................Epoch: 6/200,  Loss: 1.1400
........................................Epoch: 6/200,  Loss: 1.0711
.............................           Epoch 6 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 62.4957 %
Confusion matrix
[[175   0   1   6   3  17  37  52   0   0]
 [  0 246   5   2   1   0   0   0   2  34]
 [  5  17 130  27   2   6   6   6   2  90]
 [ 34   6  17  96   2  10  41  47  11  26]
 [  2   0   0   3 250  14   0   5  11   5]
 [ 24   0   2   2  26  98  19  93  25   1]
 [ 43   0   2   7   0   3 183  50   1   1]
 [ 30   1   1   2   8  27  17 193   7   3]
 [  1   0   0   1  21  30   0  11 223   3]
 [  4  14  20  19   4   2   0   8   0 219]]
........................................Epoch: 7/200,  Loss: 1.0754
........................................Epoch: 7/200,  Loss: 1.0963
........................................Epoch: 7/200,  Loss: 1.1692
........................................Epoch: 7/200,  Loss: 1.0612
........................................Epoch: 7/200,  Loss: 1.0542
........................................Epoch: 7/200,  Loss: 1.1343
.............................           Epoch 7 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 61.8063 %
Confusion matrix
[[209   0   0   4   4  10  35  26   3   0]
 [  0 267   2   2   2   0   0   1   1  15]
 [ 17  24  99  15   7   4   8   5   2 110]
 [ 48  12  14  93   6   6  43  32  14  22]
 [  3   0   0   2 258   6   0   4  13   4]
 [ 36   0   1   1  34  64  22  91  40   1]
 [ 60   1   3  10   0   0 184  30   2   0]
 [ 45   1   0   2  13  12  30 177   8   1]
 [  1   1   0   1  24  17   1  11 233   1]
 [  5  33   8  17   7   2   1   8   0 209]]
........................................Epoch: 8/200,  Loss: 1.0998
........................................Epoch: 8/200,  Loss: 1.0950
........................................Epoch: 8/200,  Loss: 1.0742
........................................Epoch: 8/200,  Loss: 1.0438
........................................Epoch: 8/200,  Loss: 1.0209
........................................Epoch: 8/200,  Loss: 1.1202
.............................           Epoch 8 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 61.8752 %
Confusion matrix
[[185   0   5   8   0  13  25  54   1   0]
 [  0 249  14   2   1   0   0   2   1  21]
 [  6  13 199  13   2   2   7   3   2  44]
 [ 45  10  43  97   2   4  35  36  11   7]
 [  2   0   4   2 232  29   0   6  13   2]
 [ 29   0   6   5  14  88  18 101  29   0]
 [ 52   0   4  14   0   0 166  53   1   0]
 [ 32   1   2   8   5  22  13 200   6   0]
 [  1   1   0   2  12  29   1  15 228   1]
 [  6  24  71  23   4   2   0   9   0 151]]
........................................Epoch: 9/200,  Loss: 1.0213
........................................Epoch: 9/200,  Loss: 1.0518
........................................Epoch: 9/200,  Loss: 1.0211
........................................Epoch: 9/200,  Loss: 1.0524
........................................Epoch: 9/200,  Loss: 1.0023
........................................Epoch: 9/200,  Loss: 1.1424
.............................           Epoch 9 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 63.9090 %
Confusion matrix
[[161   0   0  10   1  27  50  41   0   1]
 [  0 259   3   5   1   0   0   1   1  20]
 [  7  17  98  35   2   7   8   4   1 112]
 [ 20   7   3 147   3  12  35  39   2  22]
 [  0   1   0   3 250  21   0   3   7   5]
 [ 23   0   0   9  20 141  21  66  10   0]
 [ 33   0   2  11   0   5 190  49   0   0]
 [ 26   1   0   6   8  36  17 190   3   2]
 [  1   1   0   6  20  45   1  23 188   5]
 [  2  20   5  21   2   3   2   5   0 230]]
........................................Epoch: 10/200,  Loss: 1.0529
........................................Epoch: 10/200,  Loss: 1.0207
........................................Epoch: 10/200,  Loss: 1.0181
........................................Epoch: 10/200,  Loss: 1.0489
........................................Epoch: 10/200,  Loss: 1.0447
........................................Epoch: 10/200,  Loss: 1.0824
.............................           Epoch 10 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 62.8059 %
Confusion matrix
[[228   0   4   7   0  15   4  32   1   0]
 [  0 240  30   2   1   0   0   1   2  14]
 [  9   7 206  23   2   2   1   3   0  38]
 [ 36   6  32 154   1   7  12  33   3   6]
 [  2   0   5   4 209  58   0   3   9   0]
 [ 36   0   3  14   7 137  10  74   9   0]
 [ 87   0   4  29   0   3 123  44   0   0]
 [ 47   1   2   9   1  38   9 179   3   0]
 [  1   1   0  10   5  62   0  15 196   0]
 [  4  19  74  29   2   6   0   6   0 150]]
........................................Epoch: 11/200,  Loss: 1.0066
........................................Epoch: 11/200,  Loss: 1.0032
........................................Epoch: 11/200,  Loss: 1.1060
........................................Epoch: 11/200,  Loss: 0.9733
........................................Epoch: 11/200,  Loss: 1.0350
........................................Epoch: 11/200,  Loss: 0.9795
.............................           Epoch 11 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 62.6680 %
Confusion matrix
[[204   0   0   3   1  16  28  37   1   1]
 [  0 249  18   0   1   0   1   1   1  19]
 [ 14  12 153  15   0   3   5   4   3  82]
 [ 57   6  16  85   2  14  46  27  13  24]
 [  2   1   1   2 219  30   0   8  21   6]
 [ 25   0   0   2  11  99  18 100  34   1]
 [ 73   0   3   7   0   3 169  34   1   0]
 [ 43   1   0   4   3  26  18 187   6   1]
 [  1   0   0   1   9  17   0  23 234   5]
 [  9  15  27   8   1   3   3   5   0 219]]
........................................Epoch: 12/200,  Loss: 0.9897
........................................Epoch: 12/200,  Loss: 1.0708
........................................Epoch: 12/200,  Loss: 0.9859
........................................Epoch: 12/200,  Loss: 1.0027
........................................Epoch: 12/200,  Loss: 1.0572
........................................Epoch: 12/200,  Loss: 1.0006
.............................           Epoch 12 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 63.8056 %
Confusion matrix
[[231   0   1   7   0  34   3  14   0   1]
 [  0 257   9   3   1   0   0   0   1  19]
 [ 12  14 132  15   6   5   1   0   3 103]
 [ 55  10  16 114   4  21  16  16  13  25]
 [  3   0   3   2 237  27   0   1  16   1]
 [ 29   0   1   1  17 171   8  42  20   1]
 [102   0   4  16   0  14 117  35   1   1]
 [ 53   2   3   9   6  75   7 131   3   0]
 [  2   1   0   1  14  36   0  13 222   1]
 [  3  15   9  15   4   4   0   1   0 239]]
........................................Epoch: 13/200,  Loss: 0.9758
........................................Epoch: 13/200,  Loss: 0.9897
........................................Epoch: 13/200,  Loss: 1.0740
........................................Epoch: 13/200,  Loss: 0.9780
........................................Epoch: 13/200,  Loss: 0.9524
........................................Epoch: 13/200,  Loss: 1.0108
.............................           Epoch 13 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.5295 %
Confusion matrix
[[170   0   3   7   2  46  46  15   1   1]
 [  0 264  11   1   2   0   0   0   2  10]
 [  4  17 128  11   5   9   6   2   3 106]
 [ 28  10  11 108   5  20  45  21  15  27]
 [  0   0   2   2 250  23   0   3   7   3]
 [ 16   0   1   1  17 176  20  33  25   1]
 [ 42   1   2   9   0  17 193  23   1   2]
 [ 26   1   2   3   9  76  27 134   8   3]
 [  0   1   0   1  18  37   0   7 225   1]
 [  2  36   6  12   2   4   2   1   1 224]]
........................................Epoch: 14/200,  Loss: 1.0245
........................................Epoch: 14/200,  Loss: 0.9878
........................................Epoch: 14/200,  Loss: 0.9630
........................................Epoch: 14/200,  Loss: 0.9856
........................................Epoch: 14/200,  Loss: 1.0221
........................................Epoch: 14/200,  Loss: 1.0024
.............................           Epoch 14 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.2537 %
Confusion matrix
[[134   0   0  16   2  28  44  66   0   1]
 [  0 268   2   6   0   0   0   0   1  13]
 [  3  21 109  33   1   4   8   4   1 107]
 [ 16   8   8 160   1   7  32  31   4  23]
 [  1   0   1   2 249  19   0   2   8   8]
 [ 14   1   1   7  20 146  19  69  12   1]
 [ 31   0   2  18   0   4 177  57   1   0]
 [ 18   2   0  18   8  43  12 183   3   2]
 [  0   1   0   9  13  34   0  27 202   4]
 [  2  26   3  16   2   2   1   2   0 236]]
........................................Epoch: 15/200,  Loss: 0.9707
........................................Epoch: 15/200,  Loss: 0.9320
........................................Epoch: 15/200,  Loss: 0.9580
........................................Epoch: 15/200,  Loss: 0.9998
........................................Epoch: 15/200,  Loss: 1.0349
........................................Epoch: 15/200,  Loss: 0.9657
.............................           Epoch 15 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.3916 %
Confusion matrix
[[178   0   0   3   2  26  53  28   1   0]
 [  0 261   8   5   3   0   0   1   2  10]
 [  9  14 154  20  11  12  10   6   2  53]
 [ 40   5  13 111   5  19  46  35   5  11]
 [  2   0   0   3 246  27   0   3   9   0]
 [ 20   0   1   0  13 156  22  60  17   1]
 [ 37   0   1   2   0   5 201  44   0   0]
 [ 32   1   0   2   5  46  22 177   3   1]
 [  1   1   0   3  12  47   1  17 207   1]
 [  6  25  42  10   9   9   5   7   0 177]]
........................................Epoch: 16/200,  Loss: 0.9477
........................................Epoch: 16/200,  Loss: 1.0086
........................................Epoch: 16/200,  Loss: 0.9340
........................................Epoch: 16/200,  Loss: 0.9325
........................................Epoch: 16/200,  Loss: 0.9635
........................................Epoch: 16/200,  Loss: 0.9838
.............................           Epoch 16 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 65.3568 %
Confusion matrix
[[220   0   1   5   1  14  25  24   0   1]
 [  0 221  39   6   2   0   0   3   4  15]
 [  6   4 197  30   1   6   5   4   0  38]
 [ 36   4  21 141   1   8  33  28   7  11]
 [  3   0   2   3 230  33   0   4  12   3]
 [ 35   0   2   3  11 140  18  69  12   0]
 [ 69   0   0  15   0   5 167  34   0   0]
 [ 47   1   1  12   2  26  15 180   4   1]
 [  2   0   1   1   9  41   0  21 213   2]
 [  4   9  57  26   1   3   1   2   0 187]]
........................................Epoch: 17/200,  Loss: 0.9784
........................................Epoch: 17/200,  Loss: 0.9514
........................................Epoch: 17/200,  Loss: 0.9579
........................................Epoch: 17/200,  Loss: 0.9635
........................................Epoch: 17/200,  Loss: 0.9341
........................................Epoch: 17/200,  Loss: 0.9784
.............................           Epoch 17 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.0807 %
Confusion matrix
[[185   0   2   8   3  25  23  43   1   1]
 [  0 270   9   0   3   0   0   0   1   7]
 [  6  22 175  12   5   6   3   4   2  56]
 [ 41  18  24 114   4  14  18  29  13  15]
 [  2   3   0   2 262  13   0   1   5   2]
 [ 20   0   2   1  29 159  10  55  13   1]
 [ 57   2   2  13   0   7 164  44   1   0]
 [ 27   4   1   6   9  51   9 177   4   1]
 [  0   1   0   1  27  42   0   9 209   1]
 [  3  32  30  13   3   3   1   3   0 202]]
........................................Epoch: 18/200,  Loss: 0.9090
........................................Epoch: 18/200,  Loss: 0.9459
........................................Epoch: 18/200,  Loss: 0.9687
........................................Epoch: 18/200,  Loss: 0.9453
........................................Epoch: 18/200,  Loss: 0.9764
........................................Epoch: 18/200,  Loss: 0.9882
.............................           Epoch 18 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.2537 %
Confusion matrix
[[141   0   3  12   3  19  18  92   2   1]
 [  0 254   5  10   1   0   0   1   3  16]
 [  1  15 143  46   1   5   4  10   4  62]
 [ 12   5  11 172   1   7  17  42  14   9]
 [  0   0   0   4 236  31   0   3  16   0]
 [  9   0   0  10   8 111   9 103  39   1]
 [ 50   0   1  20   0   0 144  74   1   0]
 [ 13   1   0  10   7  25   8 217   7   1]
 [  0   1   0   1   8  29   0   5 245   1]
 [  2  14  23  37   3   5   0   5   0 201]]
........................................Epoch: 19/200,  Loss: 0.9251
........................................Epoch: 19/200,  Loss: 0.9184
........................................Epoch: 19/200,  Loss: 0.9309
........................................Epoch: 19/200,  Loss: 0.9194
........................................Epoch: 19/200,  Loss: 0.9566
........................................Epoch: 19/200,  Loss: 0.9494
.............................           Epoch 19 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 65.1155 %
Confusion matrix
[[225   0   1   5   4  19   7  29   1   0]
 [  0 250  16   2   5   0   0   0   6  11]
 [  6   8 135  28  13   9   4   5   4  79]
 [ 44   8  13 133   5  11  15  34  10  17]
 [  3   0   0   3 263  12   0   0   9   0]
 [ 27   0   1   2  31 118   9  73  28   1]
 [ 98   0   1   9   0   4 132  46   0   0]
 [ 37   1   0   7   8  36   6 188   5   1]
 [  1   1   0   1  18  24   0  12 232   1]
 [  4  18  11  24  12   3   0   5   0 213]]
........................................Epoch: 20/200,  Loss: 0.9326
........................................Epoch: 20/200,  Loss: 0.9175
........................................Epoch: 20/200,  Loss: 0.9076
........................................Epoch: 20/200,  Loss: 0.9543
........................................Epoch: 20/200,  Loss: 0.9299
........................................Epoch: 20/200,  Loss: 0.9973
.............................           Epoch 20 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 65.9083 %
Confusion matrix
[[230   0   2   7   4  10   4  33   1   0]
 [  0 259  17   3   1   0   1   0   2   7]
 [  9  12 206  19   7   4   3   3   1  27]
 [ 43  10  28 138   5   5  15  27   8  11]
 [  3   0   4   2 258  11   0   3   8   1]
 [ 39   0   1   3  25 119  15  73  15   0]
 [ 95   1   0  15   0   3 144  31   1   0]
 [ 46   1   4   8  10  26  11 178   5   0]
 [  1   1   1   1  24  28   0  10 224   0]
 [  4  17  78  18   7   2   2   6   0 156]]
........................................Epoch: 21/200,  Loss: 0.9134
........................................Epoch: 21/200,  Loss: 0.9351
........................................Epoch: 21/200,  Loss: 0.9037
........................................Epoch: 21/200,  Loss: 0.9082
........................................Epoch: 21/200,  Loss: 0.9286
........................................Epoch: 21/200,  Loss: 0.9437
.............................           Epoch 21 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 65.6670 %
Confusion matrix
[[181   0   0   7   1  14  42  44   1   1]
 [  0 269   4   4   0   0   0   1   1  11]
 [  9  25 108  36   1   6   2   9   0  95]
 [ 28   7   4 158   2  11  24  40   3  13]
 [  2   0   1   2 228  29   0   9  13   6]
 [ 20   0   0   6  10 135  11  88  20   0]
 [ 43   0   0   5   0   7 175  60   0   0]
 [ 24   1   0   7   1  29   8 213   4   2]
 [  1   2   0   4  14  28   0  20 221   0]
 [  3  31   3  24   1   6   1   4   0 217]]
........................................Epoch: 22/200,  Loss: 0.8490
........................................Epoch: 22/200,  Loss: 0.9230
........................................Epoch: 22/200,  Loss: 0.8936
........................................Epoch: 22/200,  Loss: 0.8986
........................................Epoch: 22/200,  Loss: 0.9304
........................................Epoch: 22/200,  Loss: 0.9446
.............................           Epoch 22 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.8052 %
Confusion matrix
[[130   0   2  13   2  11  45  86   1   1]
 [  0 255  16   2   1   0   2   1   2  11]
 [  3  11 180  33   0   3   6   6   2  47]
 [ 11   7  18 142   1   6  49  40   7   9]
 [  0   0   1   3 237  25   0   7  15   2]
 [ 16   0   1   2   9 117  15 109  20   1]
 [ 27   0   2   8   0   2 189  62   0   0]
 [ 20   1   1   7   5  18   7 224   5   1]
 [  0   1   0   1  10  32   0  17 228   1]
 [  3  20  39  31   1   5   3   9   1 178]]
........................................Epoch: 23/200,  Loss: 0.9086
........................................Epoch: 23/200,  Loss: 0.9324
........................................Epoch: 23/200,  Loss: 0.9050
........................................Epoch: 23/200,  Loss: 0.9418
........................................Epoch: 23/200,  Loss: 0.8607
........................................Epoch: 23/200,  Loss: 0.9242
.............................           Epoch 23 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.4250 %
Confusion matrix
[[194   0   2  10   5  19  41  19   0   1]
 [  0 252  19   3   1   0   0   2   1  12]
 [  2  11 174  24   4   9   6   5   3  53]
 [ 17   5  16 158   4  12  36  24   4  14]
 [  2   0   1   2 253  20   0   2   9   1]
 [ 24   0   1   4  23 143  18  59  17   1]
 [ 46   0   2  14   0   3 200  24   1   0]
 [ 31   1   2  13  12  38  22 163   7   0]
 [  0   1   0   2  20  28   0   8 230   1]
 [  2  26  35  20   7   3   2   6   0 189]]
........................................Epoch: 24/200,  Loss: 0.9408
........................................Epoch: 24/200,  Loss: 0.8978
........................................Epoch: 24/200,  Loss: 0.8710
........................................Epoch: 24/200,  Loss: 0.9013
........................................Epoch: 24/200,  Loss: 0.9666
........................................Epoch: 24/200,  Loss: 0.9406
.............................           Epoch 24 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.9431 %
Confusion matrix
[[177   0   3   4   1  10  51  45   0   0]
 [  0 256  21   3   1   0   1   1   1   6]
 [  9   8 228  10   3   4   8   4   1  16]
 [ 36   9  31 130   3   7  29  33   4   8]
 [  4   0   4   1 240  27   0   2  11   1]
 [ 23   0   2   3  12 151  19  69  11   0]
 [ 42   0   3   9   0   6 195  35   0   0]
 [ 32   1   2   4   7  27  22 191   3   0]
 [  0   0   1   5  14  45   0  20 204   1]
 [  8  30 107  17   3   6   1   6   0 112]]
........................................Epoch: 25/200,  Loss: 0.9253
........................................Epoch: 25/200,  Loss: 0.8840
........................................Epoch: 25/200,  Loss: 0.8845
........................................Epoch: 25/200,  Loss: 0.9126
........................................Epoch: 25/200,  Loss: 0.9135
........................................Epoch: 25/200,  Loss: 0.8737
.............................           Epoch 25 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.3220 %
Confusion matrix
[[241   0   0  10   2   6  18  12   1   1]
 [  0 254  20   5   1   0   1   0   2   7]
 [  9  10 204  20   3   4   3   3   0  35]
 [ 37   8  26 147   3   5  28  20   4  12]
 [  3   0   5   3 247  19   0   1  10   2]
 [ 58   0   2   2  20 111  23  48  25   1]
 [ 83   0   2  10   0   2 181  12   0   0]
 [ 63   1   2   7   7  20  48 134   6   1]
 [  2   1   1   2  17  16   0   6 243   2]
 [  6  25  67  20   3   2   3   2   0 162]]
........................................Epoch: 26/200,  Loss: 0.9184
........................................Epoch: 26/200,  Loss: 0.8830
........................................Epoch: 26/200,  Loss: 0.8877
........................................Epoch: 26/200,  Loss: 0.9417
........................................Epoch: 26/200,  Loss: 0.8799
........................................Epoch: 26/200,  Loss: 0.8755
.............................           Epoch 26 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.6667 %
Confusion matrix
[[169   0   2  21   5   4  66  21   2   1]
 [  0 248  12  12   0   0   0   0   2  16]
 [  4   8 168  33   1   2   5   1   3  66]
 [ 10   3  13 176   2   2  37  22   7  18]
 [  3   0   3   2 252   6   0   1  18   5]
 [ 30   0   1   6  26  86  32  74  34   1]
 [ 35   0   1  16   0   0 214  23   1   0]
 [ 33   1   1  17   6  13  44 165   7   2]
 [  2   1   0   2  15  15   1  10 241   3]
 [  2  18  27  18   4   1   2   3   0 215]]
........................................Epoch: 27/200,  Loss: 0.8420
........................................Epoch: 27/200,  Loss: 0.8364
........................................Epoch: 27/200,  Loss: 0.8789
........................................Epoch: 27/200,  Loss: 0.9422
........................................Epoch: 27/200,  Loss: 0.9173
........................................Epoch: 27/200,  Loss: 0.8660
.............................           Epoch 27 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 65.9428 %
Confusion matrix
[[224   0   3   3   3  25  11  20   1   1]
 [  0 237  26   2   5   0   1   0   3  16]
 [  6   6 189   9   6   7   5   2   0  61]
 [ 44   4  34  87   6  13  33  35  12  22]
 [  3   0   0   2 261  10   0   0  12   2]
 [ 29   0   2   0  31 139   8  50  30   1]
 [ 82   0   1   4   0   5 164  33   1   0]
 [ 38   1   2   0  12  47  11 172   6   0]
 [  1   1   1   0  21  17   1   7 239   2]
 [  4  10  49   5   5   5   3   7   1 201]]
........................................Epoch: 28/200,  Loss: 0.8902
........................................Epoch: 28/200,  Loss: 0.9504
........................................Epoch: 28/200,  Loss: 0.8606
........................................Epoch: 28/200,  Loss: 0.8738
........................................Epoch: 28/200,  Loss: 0.8683
........................................Epoch: 28/200,  Loss: 0.8074
.............................           Epoch 28 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 60.9445 %
Confusion matrix
[[263   0   0   3   0   3   2  19   0   1]
 [  1 198  57  16   1   0   1   3   2  11]
 [ 27   2 192  30   1   2   5   7   2  23]
 [ 76   1  17 114   2   3  33  31   6   7]
 [  9   0   2   2 226  29   1   9  11   1]
 [ 69   0   1   1  10  85  18  89  16   1]
 [121   0   2   3   0   0 145  19   0   0]
 [ 76   1   0   3   1  13  20 172   2   1]
 [  7   0   1   2  12  25   2  27 214   0]
 [ 11   7  71  21   2   2   4  13   0 159]]
........................................Epoch: 29/200,  Loss: 0.9153
........................................Epoch: 29/200,  Loss: 0.8660
........................................Epoch: 29/200,  Loss: 0.8776
........................................Epoch: 29/200,  Loss: 0.8461
........................................Epoch: 29/200,  Loss: 0.9211
........................................Epoch: 29/200,  Loss: 0.8885
.............................           Epoch 29 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.0800 %
Confusion matrix
[[180   0   4  10   3  23  37  33   1   0]
 [  0 247  23   4   3   0   1   1   2   9]
 [  3   7 189  29   2   6   4   3   3  45]
 [ 11   4  20 161   2   7  31  34   9  11]
 [  1   0   2   3 248  15   0   4  17   0]
 [ 20   0   1   4  14 141  18  63  29   0]
 [ 42   0   2  10   0   6 196  34   0   0]
 [ 23   1   2   7   8  34  24 182   8   0]
 [  0   1   0   3  14  22   0   4 245   1]
 [  3  13  45  23   3   5   3   9   0 186]]
........................................Epoch: 30/200,  Loss: 0.8701
........................................Epoch: 30/200,  Loss: 0.8777
........................................Epoch: 30/200,  Loss: 0.8104
........................................Epoch: 30/200,  Loss: 0.8962
........................................Epoch: 30/200,  Loss: 0.8897
........................................Epoch: 30/200,  Loss: 0.8894
.............................           Epoch 30 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.5288 %
Confusion matrix
[[191   0   2   6   4  59   3  25   1   0]
 [  0 256  17   2   3   0   0   0   2  10]
 [  3   8 162  37   4  11   2   2   4  58]
 [ 30  11   8 156   3  20  18  25   8  11]
 [  0   0   1   3 248  27   0   1  10   0]
 [ 15   0   1   3  10 224   3  22  11   1]
 [ 73   0   1  12   0  26 153  25   0   0]
 [ 22   1   0   7   7 110   8 128   5   1]
 [  0   1   0   3  11  56   0   1 217   1]
 [  4  25  26  24   5   4   1   6   0 195]]
........................................Epoch: 31/200,  Loss: 0.8717
........................................Epoch: 31/200,  Loss: 0.8313
........................................Epoch: 31/200,  Loss: 0.8570
........................................Epoch: 31/200,  Loss: 0.8655
........................................Epoch: 31/200,  Loss: 0.8450
........................................Epoch: 31/200,  Loss: 0.9487
.............................           Epoch 31 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 65.4947 %
Confusion matrix
[[216   0   0  11  11   6  28  19   0   0]
 [  0 267  12   4   3   0   0   0   1   3]
 [  5  17 193  29   7   4   4   4   1  27]
 [ 31  10  22 157  10   4  24  19   7   6]
 [  3   0   0   1 277   4   0   0   5   0]
 [ 35   0   2   6  60  83  18  67  19   0]
 [ 68   0   0  11   0   3 184  24   0   0]
 [ 47   2   3   7  20  23  21 161   5   0]
 [  2   1   0   1  37  17   0   8 223   1]
 [  4  33  71  23  14   2   1   3   0 139]]
........................................Epoch: 32/200,  Loss: 0.8486
........................................Epoch: 32/200,  Loss: 0.8503
........................................Epoch: 32/200,  Loss: 0.8621
........................................Epoch: 32/200,  Loss: 0.8925
........................................Epoch: 32/200,  Loss: 0.8484
........................................Epoch: 32/200,  Loss: 0.8669
.............................           Epoch 32 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.9421 %
Confusion matrix
[[172   1   2  22   1  18  39  35   0   1]
 [  0 275   5   1   1   0   1   0   0   7]
 [  2  21 165  37   0   3   2   2   2  57]
 [ 12  13  13 175   2   9  31  24   1  10]
 [  3   1   1   4 246  21   1   1  11   1]
 [ 20   0   1   4  17 167  15  55   9   2]
 [ 40   0   0   9   0  15 189  37   0   0]
 [ 31   3   1   9   3  52   8 178   3   1]
 [  2   1   0   6  17  36   4  13 209   2]
 [  2  32  22  30   1   4   1   3   0 195]]
........................................Epoch: 33/200,  Loss: 0.8574
........................................Epoch: 33/200,  Loss: 0.8498
........................................Epoch: 33/200,  Loss: 0.8929
........................................Epoch: 33/200,  Loss: 0.8570
........................................Epoch: 33/200,  Loss: 0.8570
........................................Epoch: 33/200,  Loss: 0.8382
.............................           Epoch 33 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 64.7018 %
Confusion matrix
[[202   0   0   4   2  22  33  28   0   0]
 [  0 233  33   6   3   0   2   6   2   5]
 [  9   5 183  33   7   9  12   9   1  23]
 [ 43   4  10 120   3   5  48  40   8   9]
 [  3   0   0   3 239  21   0   2  22   0]
 [ 24   0   1   1  10 139  20  72  22   1]
 [ 52   0   0   2   0   4 190  42   0   0]
 [ 33   0   0   1   4  32  18 197   3   1]
 [  1   1   0   1   8  39   0  13 223   4]
 [  8  15  57  26  10   6   4  13   0 151]]
........................................Epoch: 34/200,  Loss: 0.7929
........................................Epoch: 34/200,  Loss: 0.8657
........................................Epoch: 34/200,  Loss: 0.8685
........................................Epoch: 34/200,  Loss: 0.8903
........................................Epoch: 34/200,  Loss: 0.8625
........................................Epoch: 34/200,  Loss: 0.8332
.............................           Epoch 34 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.9080 %
Confusion matrix
[[207   0   3   3   5  32  14  27   0   0]
 [  0 243  23   1   4   0   1   1   2  15]
 [  6   6 185  18   3   7   2   3   0  61]
 [ 52   5  22 121   3  10  26  29   8  14]
 [  4   0   0   0 265  13   0   1   7   0]
 [ 25   0   1   2  25 156  12  49  18   2]
 [ 69   0   1   7   0   9 161  43   0   0]
 [ 34   1   0   3  11  50  10 173   6   1]
 [  1   1   1   1  23  24   1  10 227   1]
 [  7  12  40  13   6   3   1   5   0 203]]
........................................Epoch: 35/200,  Loss: 0.9048
........................................Epoch: 35/200,  Loss: 0.8270
........................................Epoch: 35/200,  Loss: 0.8589
........................................Epoch: 35/200,  Loss: 0.8343
........................................Epoch: 35/200,  Loss: 0.8557
........................................Epoch: 35/200,  Loss: 0.8972
.............................           Epoch 35 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.3564 %
Confusion matrix
[[168   0   2   8   3  29  25  56   0   0]
 [  0 276   3   2   3   0   1   0   1   4]
 [  4  23 141  30   3  10   3   7   3  67]
 [ 25  15  11 138   2  14  25  39   8  13]
 [  3   0   0   1 253  21   0   1  10   1]
 [ 15   0   1   1  13 179  12  61   7   1]
 [ 49   0   0   6   0   8 175  52   0   0]
 [ 16   2   0   3   7  52  10 197   1   1]
 [  0   1   0   3  13  57   0  13 201   2]
 [  2  35  19  17   2  10   2   6   0 197]]
........................................Epoch: 36/200,  Loss: 0.8069
........................................Epoch: 36/200,  Loss: 0.8214
........................................Epoch: 36/200,  Loss: 0.8511
........................................Epoch: 36/200,  Loss: 0.8555
........................................Epoch: 36/200,  Loss: 0.8661
........................................Epoch: 36/200,  Loss: 0.8324
.............................           Epoch 36 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.6667 %
Confusion matrix
[[187   0   0   8   3  13  60  18   1   1]
 [  0 273   8   2   0   0   4   0   2   1]
 [  8  24 184  19   1   3  11   1   0  40]
 [ 36   9  21 140   3   6  40  20   3  12]
 [  3   1   3   4 244  17   1   0  16   1]
 [ 34   0   1   2  17 146  28  40  19   3]
 [ 43   0   0   4   0   2 220  21   0   0]
 [ 45   1   1   4   8  40  32 152   5   1]
 [  2   3   1   3  12  31   5   8 224   1]
 [  3  53  41  15   2   3   6   3   0 164]]
........................................Epoch: 37/200,  Loss: 0.8203
........................................Epoch: 37/200,  Loss: 0.8624
........................................Epoch: 37/200,  Loss: 0.8386
........................................Epoch: 37/200,  Loss: 0.8368
........................................Epoch: 37/200,  Loss: 0.8608
........................................Epoch: 37/200,  Loss: 0.9267
.............................           Epoch 37 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.1489 %
Confusion matrix
[[195   0   0  10   1  16  49  16   3   1]
 [  0 255  19   2   1   0   0   0   2  11]
 [  5   9 203  27   1   6   8   1   4  27]
 [ 27   4  16 161   3   9  34  15  12   9]
 [  2   1   1   1 237  28   0   2  16   2]
 [ 27   0   1   3  12 144  19  45  38   1]
 [ 44   0   0  10   0   5 213  17   1   0]
 [ 39   1   1   5   8  43  41 141   9   1]
 [  2   1   0   1   8  17   1   5 255   0]
 [  2  18  63  21   3   5   1   4   0 173]]
........................................Epoch: 38/200,  Loss: 0.8535
........................................Epoch: 38/200,  Loss: 0.7963
........................................Epoch: 38/200,  Loss: 0.8007
........................................Epoch: 38/200,  Loss: 0.7970
........................................Epoch: 38/200,  Loss: 0.8444
........................................Epoch: 38/200,  Loss: 0.8725
.............................           Epoch 38 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.3561 %
Confusion matrix
[[227   0   2   4   1  16  20  20   1   0]
 [  0 260  22   3   0   0   0   0   2   3]
 [ 13  10 236  12   1   5   1   2   2   9]
 [ 52   5  35 125   2  13  18  29   5   6]
 [  4   0   2   1 239  26   0   4  12   2]
 [ 31   0   3   2  11 163  12  56  12   0]
 [ 63   0   1   8   0  10 174  33   0   1]
 [ 41   1   2   3   3  36  11 189   3   0]
 [  2   1   1   1   9  41   1  13 221   0]
 [ 10  34 102  11   2   4   1   6   0 120]]
........................................Epoch: 39/200,  Loss: 0.8870
........................................Epoch: 39/200,  Loss: 0.8382
........................................Epoch: 39/200,  Loss: 0.8499
........................................Epoch: 39/200,  Loss: 0.8640
........................................Epoch: 39/200,  Loss: 0.8372
........................................Epoch: 39/200,  Loss: 0.8069
.............................           Epoch 39 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.7356 %
Confusion matrix
[[237   0   0  22   1   8  10  12   0   1]
 [  0 261  15   2   0   0   1   0   2   9]
 [  4  12 159  38   1   5   1   2   2  67]
 [ 23   7   8 211   2   2  14   5   4  14]
 [  2   0   1   7 242  20   0   2  14   2]
 [ 50   0   1  20  15 134   8  36  23   3]
 [110   0   1  38   0   6 121  14   0   0]
 [ 84   3   2  35   4  38  10 107   5   1]
 [  2   1   0   5  12  17   1   5 245   2]
 [  2  13  23  26   3   2   1   1   0 219]]
........................................Epoch: 40/200,  Loss: 0.8570
........................................Epoch: 40/200,  Loss: 0.7921
........................................Epoch: 40/200,  Loss: 0.8383
........................................Epoch: 40/200,  Loss: 0.8159
........................................Epoch: 40/200,  Loss: 0.8693
........................................Epoch: 40/200,  Loss: 0.8559
.............................           Epoch 40 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.6663 %
Confusion matrix
[[169   0   0   9   1  14  58  38   1   1]
 [  0 242  23   7   0   0   0   2   3  13]
 [  4   3 169  37   1   5   8   5   2  57]
 [ 19   3  12 156   1   5  38  37   6  13]
 [  1   0   1   1 239  24   0   7  17   0]
 [ 17   0   1   3  15 123  26  80  25   0]
 [ 32   0   0   4   0   2 220  30   2   0]
 [ 28   1   1   3   1  24  24 199   7   1]
 [  2   1   0   1  11  22   1   9 242   1]
 [  4  10  33  22   2   4   4   7   0 204]]
........................................Epoch: 41/200,  Loss: 0.8315
........................................Epoch: 41/200,  Loss: 0.7960
........................................Epoch: 41/200,  Loss: 0.8330
........................................Epoch: 41/200,  Loss: 0.8220
........................................Epoch: 41/200,  Loss: 0.8066
........................................Epoch: 41/200,  Loss: 0.8412
.............................           Epoch 41 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.0114 %
Confusion matrix
[[243   0   0   6   1  13  11  16   0   1]
 [  0 264   8   1   2   0   0   2   2  11]
 [ 15  14 170  21   6   3   6   3   1  52]
 [ 58   8  18 127   5   7  30  16   6  15]
 [  4   0   0   0 257  22   0   0   6   1]
 [ 39   0   1   1  19 143  19  56  11   1]
 [ 99   0   1   4   0   3 170  13   0   0]
 [ 69   3   1   4   4  32  20 154   2   0]
 [  2   1   1   0  20  28   2  11 219   6]
 [  9  21  32  14   4   6   2   5   0 197]]
........................................Epoch: 42/200,  Loss: 0.8103
........................................Epoch: 42/200,  Loss: 0.8236
........................................Epoch: 42/200,  Loss: 0.8158
........................................Epoch: 42/200,  Loss: 0.8716
........................................Epoch: 42/200,  Loss: 0.8376
........................................Epoch: 42/200,  Loss: 0.8423
.............................           Epoch 42 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.9417 %
Confusion matrix
[[223   0   2  16   1  19  13  15   1   1]
 [  0 241  20   9   1   0   0   0   2  17]
 [  3   6 183  23   1   6   3   0   1  65]
 [ 21   4  19 167   4  11  26  13   5  20]
 [  1   0   1   4 252  21   0   0   9   2]
 [ 29   0   2   2  26 177  12  30  11   1]
 [ 72   0   1  12   0   9 178  18   0   0]
 [ 53   1   3  11   5  58  21 133   4   0]
 [  2   1   0   1  16  27   2   7 230   4]
 [  2   6  41  19   2   3   0   1   0 216]]
........................................Epoch: 43/200,  Loss: 0.8486
........................................Epoch: 43/200,  Loss: 0.7912
........................................Epoch: 43/200,  Loss: 0.8256
........................................Epoch: 43/200,  Loss: 0.8687
........................................Epoch: 43/200,  Loss: 0.7940
........................................Epoch: 43/200,  Loss: 0.8284
.............................           Epoch 43 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.4250 %
Confusion matrix
[[205   0   0   8   1  20  35  20   1   1]
 [  0 265   9   3   3   0   0   1   3   6]
 [  8  14 132  50   2  11   9   6   3  56]
 [ 34   6   4 158   2  14  29  30   5   8]
 [  3   0   0   1 250  17   0   1  16   2]
 [ 19   0   1   1  17 175  18  46  12   1]
 [ 59   0   0   7   0  12 191  21   0   0]
 [ 34   1   0   4   5  50  28 162   4   1]
 [  1   1   0   4  11  31   2   6 234   0]
 [  5  28  21  34   4   4   3   7   0 184]]
........................................Epoch: 44/200,  Loss: 0.8508
........................................Epoch: 44/200,  Loss: 0.8314
........................................Epoch: 44/200,  Loss: 0.7870
........................................Epoch: 44/200,  Loss: 0.8009
........................................Epoch: 44/200,  Loss: 0.8151
........................................Epoch: 44/200,  Loss: 0.8103
.............................           Epoch 44 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.1834 %
Confusion matrix
[[156   0   1   9   3  37  46  36   2   1]
 [  0 257  12   3   2   0   1   0   4  11]
 [  3   8 176  40   3   7   1   3   2  48]
 [ 27   5  11 158   5  17  27  24   5  11]
 [  1   0   0   4 253  23   0   0   9   0]
 [ 11   0   0   5  10 210  12  33   8   1]
 [ 31   0   0  17   0  19 199  24   0   0]
 [ 18   1   1   8   8  75  19 156   2   1]
 [  0   1   0   3   9  40   0  10 227   0]
 [  2  24  42  18   3   6   2   7   0 186]]
........................................Epoch: 45/200,  Loss: 0.7653
........................................Epoch: 45/200,  Loss: 0.8120
........................................Epoch: 45/200,  Loss: 0.7763
........................................Epoch: 45/200,  Loss: 0.8625
........................................Epoch: 45/200,  Loss: 0.8506
........................................Epoch: 45/200,  Loss: 0.8165
.............................           Epoch 45 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.5629 %
Confusion matrix
[[229   0   0   3   1  21  12  24   1   0]
 [  0 247  17   7   1   0   1   6   4   7]
 [  9   6 208  23   1   7   7   7   2  21]
 [ 49   4  18 139   2  11  27  22  12   6]
 [  1   0   2   1 227  34   0   4  21   0]
 [ 24   0   1   1   2 168  10  60  23   1]
 [ 78   0   1   7   0   9 163  31   1   0]
 [ 40   0   0   2   3  43   8 187   6   0]
 [  2   1   0   1   7  27   0  10 242   0]
 [  6  25  63  25   2   9   2   8   0 150]]
........................................Epoch: 46/200,  Loss: 0.7962
........................................Epoch: 46/200,  Loss: 0.8210
........................................Epoch: 46/200,  Loss: 0.7885
........................................Epoch: 46/200,  Loss: 0.7762
........................................Epoch: 46/200,  Loss: 0.8199
........................................Epoch: 46/200,  Loss: 0.8216
.............................           Epoch 46 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.4940 %
Confusion matrix
[[239   0   0   5   1   8  19  18   0   1]
 [  0 243  17   7   3   0   0   0   3  17]
 [ 13   7 173  31   2   3   8   4   3  47]
 [ 49   4  11 135   3   8  37  26   4  13]
 [  2   0   1   2 243  20   0   2  19   1]
 [ 45   0   1   1  18 127  15  66  16   1]
 [ 85   0   0   2   0   3 177  23   0   0]
 [ 53   1   0   3   5  25  22 177   2   1]
 [  2   1   0   1   9  21   1  13 240   2]
 [ 10  15  33  16   1   3   3   5   0 204]]
........................................Epoch: 47/200,  Loss: 0.8276
........................................Epoch: 47/200,  Loss: 0.7594
........................................Epoch: 47/200,  Loss: 0.7951
........................................Epoch: 47/200,  Loss: 0.7939
........................................Epoch: 47/200,  Loss: 0.8443
........................................Epoch: 47/200,  Loss: 0.8349
.............................           Epoch 47 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.0452 %
Confusion matrix
[[177   0   0  13   1  25  31  41   2   1]
 [  0 274   4   1   0   0   0   1   2   8]
 [  2  20 137  42   0   7   3   5   3  72]
 [ 18   9   9 164   3  13  24  25  11  14]
 [  0   0   0   1 250  25   0   3  10   1]
 [ 16   0   1   4   9 156  11  71  21   1]
 [ 40   0   0  14   0   8 186  41   1   0]
 [ 18   1   0   6   5  38  14 200   6   1]
 [  1   1   0   1  11  24   0   7 244   1]
 [  2  27  13  20   2   6   1   4   0 215]]
........................................Epoch: 48/200,  Loss: 0.7897
........................................Epoch: 48/200,  Loss: 0.7864
........................................Epoch: 48/200,  Loss: 0.8570
........................................Epoch: 48/200,  Loss: 0.7590
........................................Epoch: 48/200,  Loss: 0.7742
........................................Epoch: 48/200,  Loss: 0.8279
.............................           Epoch 48 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.5629 %
Confusion matrix
[[222   0   2   7   5  19  15  17   3   1]
 [  0 251  22   3   1   0   1   0   3   9]
 [  5   3 218  15   2   6   4   1   2  35]
 [ 29   7  34 136   5   7  25  23  12  12]
 [  0   0   2   0 252  14   0   3  18   1]
 [ 29   0   5   0  19 147   8  52  29   1]
 [ 80   0   1   8   0  12 159  27   1   2]
 [ 43   3   1   8   6  46  12 160   9   1]
 [  2   1   0   1  16  23   0   4 242   1]
 [  4  19  71  14   3   0   2   3   1 173]]
........................................Epoch: 49/200,  Loss: 0.7863
........................................Epoch: 49/200,  Loss: 0.7805
........................................Epoch: 49/200,  Loss: 0.7751
........................................Epoch: 49/200,  Loss: 0.7991
........................................Epoch: 49/200,  Loss: 0.8230
........................................Epoch: 49/200,  Loss: 0.8240
.............................           Epoch 49 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.4936 %
Confusion matrix
[[187   0   4  23   7  19  27  22   2   0]
 [  0 248  25   2   3   0   0   0   4   8]
 [  2   3 223  21   3   2   3   3   4  27]
 [ 12   6  22 186   7   8  18  16   5  10]
 [  0   0   0   3 267   6   0   2  12   0]
 [ 23   0   4   6  36 135   9  41  35   1]
 [ 48   0   1  27   0   5 176  30   3   0]
 [ 29   1   3  15  10  43  23 154   9   2]
 [  2   1   0   1  28   8   1   5 243   1]
 [  2  14  73  22   5   3   1   2   0 168]]
........................................Epoch: 50/200,  Loss: 0.8154
........................................Epoch: 50/200,  Loss: 0.7973
........................................Epoch: 50/200,  Loss: 0.8052
........................................Epoch: 50/200,  Loss: 0.7922
........................................Epoch: 50/200,  Loss: 0.8052
........................................Epoch: 50/200,  Loss: 0.7674
.............................           Epoch 50 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.5629 %
Confusion matrix
[[206   0   0   8   1  11  39  25   0   1]
 [  0 245  25   4   0   0   2   2   1  11]
 [  7   6 193  36   0   3   7   3   0  36]
 [ 34   4  16 155   2   8  34  22   5  10]
 [  3   0   2   6 216  32   0   7  24   0]
 [ 28   0   1   3   8 159  13  65  12   1]
 [ 47   0   0  12   0   6 196  29   0   0]
 [ 40   1   1  13   1  29  23 177   2   2]
 [  2   1   0   2   4  39   3  10 228   1]
 [  4  14  44  28   1   6   3   5   0 185]]
........................................Epoch: 51/200,  Loss: 0.8032
........................................Epoch: 51/200,  Loss: 0.7590
........................................Epoch: 51/200,  Loss: 0.7871
........................................Epoch: 51/200,  Loss: 0.7960
........................................Epoch: 51/200,  Loss: 0.7956
........................................Epoch: 51/200,  Loss: 0.8030
.............................           Epoch 51 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.9421 %
Confusion matrix
[[148   0   5  11   5  16  40  60   5   1]
 [  0 241  26   3   2   0   0   0   4  14]
 [  2   3 211  16   1   4   4   4   5  41]
 [ 25   4  28 150   3  13  21  23  10  13]
 [  1   0   2   1 243  22   0   3  18   0]
 [ 14   0   3   1  18 157   9  59  26   3]
 [ 31   0   0  15   0  12 182  47   2   1]
 [ 18   1   2   3  12  40  16 188   9   0]
 [  1   1   0   1  16  24   0   5 241   1]
 [  2  10  49   9   3   6   0   1   0 210]]
........................................Epoch: 52/200,  Loss: 0.7515
........................................Epoch: 52/200,  Loss: 0.8233
........................................Epoch: 52/200,  Loss: 0.7694
........................................Epoch: 52/200,  Loss: 0.8715
........................................Epoch: 52/200,  Loss: 0.7917
........................................Epoch: 52/200,  Loss: 0.7977
.............................           Epoch 52 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.2520 %
Confusion matrix
[[203   0   0   5   1  18  27  35   1   1]
 [  0 258  15   3   0   0   0   1   2  11]
 [  6   9 165  26   1   6   9   3   2  64]
 [ 31   5  18 135   4  13  41  26   4  13]
 [  2   0   0   1 252  22   1   2   9   1]
 [ 24   0   2   2  15 150   9  67  19   2]
 [ 51   0   0   4   0   7 198  30   0   0]
 [ 29   1   0   7   4  33  24 187   3   1]
 [  1   1   0   2  12  24   1   8 240   1]
 [  2  15  22  17   1   5   4   3   0 221]]
........................................Epoch: 53/200,  Loss: 0.7639
........................................Epoch: 53/200,  Loss: 0.7478
........................................Epoch: 53/200,  Loss: 0.8280
........................................Epoch: 53/200,  Loss: 0.8288
........................................Epoch: 53/200,  Loss: 0.7446
........................................Epoch: 53/200,  Loss: 0.7900
.............................           Epoch 53 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.2182 %
Confusion matrix
[[170   0   1   5   5   8  47  51   4   0]
 [  0 257  21   2   0   0   2   2   4   2]
 [  7   9 226  11   2   3   7   5   5  16]
 [ 28   5  33 112   5  12  39  34  14   8]
 [  0   0   3   0 244  10   0   5  28   0]
 [ 18   0   3   2  17 118  12  86  34   0]
 [ 33   0   0   2   0   5 214  34   2   0]
 [ 25   1   2   0   7  14  29 208   3   0]
 [  1   1   1   1  15  11   1  10 248   1]
 [  3  25  84   7   4   4   5   5   0 153]]
........................................Epoch: 54/200,  Loss: 0.7849
........................................Epoch: 54/200,  Loss: 0.7988
........................................Epoch: 54/200,  Loss: 0.7936
........................................Epoch: 54/200,  Loss: 0.7832
........................................Epoch: 54/200,  Loss: 0.7529
........................................Epoch: 54/200,  Loss: 0.7791
.............................           Epoch 54 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.1486 %
Confusion matrix
[[165   0   1  11   6   6  61  38   3   0]
 [  0 266  13   2   0   0   0   1   2   6]
 [  6  14 200  23   0   3  10   2   3  30]
 [ 22   5  15 157   4   4  40  23  11   9]
 [  1   1   1   2 259   6   2   2  16   0]
 [ 17   0   0   5  26  92  21  86  43   0]
 [ 21   0   0   8   0   2 228  29   2   0]
 [ 25   1   1   7   6  12  29 197  10   1]
 [  2   1   0   1  17   5   2   6 255   1]
 [  2  22  45  22   2   2   2   5   1 187]]
........................................Epoch: 55/200,  Loss: 0.7689
........................................Epoch: 55/200,  Loss: 0.8223
........................................Epoch: 55/200,  Loss: 0.7640
........................................Epoch: 55/200,  Loss: 0.7983
........................................Epoch: 55/200,  Loss: 0.7836
........................................Epoch: 55/200,  Loss: 0.8026
.............................           Epoch 55 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.7697 %
Confusion matrix
[[229   0   1  12   7   6  25  10   1   0]
 [  0 273   6   6   0   0   0   0   2   3]
 [  8  19 160  39   3   4   5   1   1  51]
 [ 36   7   8 174   5   5  24  12   8  11]
 [  4   1   0   0 266   6   0   0  12   1]
 [ 54   0   1   3  39 111  14  40  24   4]
 [ 76   0   0   8   0   6 178  22   0   0]
 [ 72   2   0  18  11  30  18 135   3   0]
 [  2   1   0   1  23   8   0   6 248   1]
 [  5  40  15  25   4   3   3   3   0 192]]
........................................Epoch: 56/200,  Loss: 0.7567
........................................Epoch: 56/200,  Loss: 0.7965
........................................Epoch: 56/200,  Loss: 0.8304
........................................Epoch: 56/200,  Loss: 0.8545
........................................Epoch: 56/200,  Loss: 0.7481
........................................Epoch: 56/200,  Loss: 0.8204
.............................           Epoch 56 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.0107 %
Confusion matrix
[[207   0   1   9   5  15  17  33   3   1]
 [  0 273   4   1   0   0   0   0   4   8]
 [  5  19 171  15   2   8   3   2   5  61]
 [ 28   9  16 146   2  14  22  24  10  19]
 [  2   1   1   0 252  11   0   1  21   1]
 [ 30   0   2   3  21 138   9  48  37   2]
 [ 70   0   0   6   0  10 169  32   2   1]
 [ 34   1   2   5   6  42  12 178   6   3]
 [  2   0   0   1  13  16   0   3 255   0]
 [  2  25  26  15   2   3   2   2   0 213]]
........................................Epoch: 57/200,  Loss: 0.7401
........................................Epoch: 57/200,  Loss: 0.7642
........................................Epoch: 57/200,  Loss: 0.8141
........................................Epoch: 57/200,  Loss: 0.7915
........................................Epoch: 57/200,  Loss: 0.7865
........................................Epoch: 57/200,  Loss: 0.7770
.............................           Epoch 57 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.1144 %
Confusion matrix
[[206   0   0  12   7  14  22  29   1   0]
 [  0 267   8   4   1   0   0   0   3   7]
 [  7  11 126  49   4   5   5   6   2  76]
 [ 21   6   5 178   3  11  23  22   7  14]
 [  3   0   0   1 272   9   0   1   4   0]
 [ 24   0   0   4  30 143  11  59  17   2]
 [ 65   0   0  15   0   8 172  29   0   1]
 [ 34   3   0  10  12  33  13 175   7   2]
 [  2   1   0   4  21  26   0   8 227   1]
 [  3  22  10  32   6   2   2   3   0 210]]
........................................Epoch: 58/200,  Loss: 0.7749
........................................Epoch: 58/200,  Loss: 0.8199
........................................Epoch: 58/200,  Loss: 0.8326
........................................Epoch: 58/200,  Loss: 0.7810
........................................Epoch: 58/200,  Loss: 0.7402
........................................Epoch: 58/200,  Loss: 0.7850
.............................           Epoch 58 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.0796 %
Confusion matrix
[[211   0   0  10   3  17  26  23   1   0]
 [  0 256   8  11   1   0   0   1   4   9]
 [ 12  11 192  25   3   3   2   2   3  38]
 [ 38   4  11 152   2   8  28  24  14   9]
 [  4   0   0   0 250  21   0   0  14   1]
 [ 26   0   1   1  13 154  13  51  29   2]
 [ 70   0   0   7   0   6 178  26   2   1]
 [ 39   2   0   4   4  42  17 171   9   1]
 [  3   1   0   1  12  17   1   2 253   0]
 [  3  19  44  26   1   4   2   4   0 187]]
........................................Epoch: 59/200,  Loss: 0.7464
........................................Epoch: 59/200,  Loss: 0.7968
........................................Epoch: 59/200,  Loss: 0.7702
........................................Epoch: 59/200,  Loss: 0.7532
........................................Epoch: 59/200,  Loss: 0.8307
........................................Epoch: 59/200,  Loss: 0.8392
.............................           Epoch 59 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 70.1482 %
Confusion matrix
[[207   0   2   9   4  18  30  20   0   1]
 [  0 266   6   2   1   0   0   0   3  12]
 [  6  15 164  27   2   5   5   0   4  63]
 [ 26   3  13 170   3  14  22  15   7  17]
 [  3   0   0   2 260   9   0   0  15   1]
 [ 28   0   1   2  21 180   7  32  16   3]
 [ 49   0   0   6   0  17 188  29   0   1]
 [ 37   2   1   9   5  63  18 147   6   1]
 [  2   1   0   1  17  34   1   4 227   3]
 [  4  11  19  18   1   6   3   2   0 226]]
........................................Epoch: 60/200,  Loss: 0.7014
........................................Epoch: 60/200,  Loss: 0.7563
........................................Epoch: 60/200,  Loss: 0.7912
........................................Epoch: 60/200,  Loss: 0.7540
........................................Epoch: 60/200,  Loss: 0.7796
........................................Epoch: 60/200,  Loss: 0.8003
.............................           Epoch 60 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.3561 %
Confusion matrix
[[191   0   0  12   2  15  12  59   0   0]
 [  0 251  19   8   1   0   0   2   3   6]
 [  6   4 180  55   3   6   4   6   3  24]
 [ 25   3   4 186   2  10  18  29   8   5]
 [  0   0   1   2 231  18   0  11  27   0]
 [ 15   0   1   2   8 140   7  94  22   1]
 [ 62   0   0  16   0   9 152  50   0   1]
 [ 24   0   1   6   1  33   6 213   4   1]
 [  2   1   0   1   9  21   0  11 244   1]
 [  4  16  41  47   2   4   1   9   0 166]]
........................................Epoch: 61/200,  Loss: 0.7629
........................................Epoch: 61/200,  Loss: 0.7787
........................................Epoch: 61/200,  Loss: 0.7265
........................................Epoch: 61/200,  Loss: 0.7749
........................................Epoch: 61/200,  Loss: 0.7908
........................................Epoch: 61/200,  Loss: 0.7571
.............................           Epoch 61 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.3554 %
Confusion matrix
[[224   0   2   8   6  21  15  13   2   0]
 [  0 261  17   3   1   0   0   0   3   5]
 [  6   9 218  19   2   7   3   2   1  24]
 [ 31   7  25 164   4  15  16  14   8   6]
 [  3   0   1   1 268   7   0   0  10   0]
 [ 26   0   2   2  28 164   8  30  29   1]
 [ 69   0   0  14   0  10 174  20   3   0]
 [ 46   1   2   8   9  62  15 139   7   0]
 [  2   1   0   1  20  10   1   3 251   1]
 [  3  19  76  26   6   5   2   4   0 149]]
........................................Epoch: 62/200,  Loss: 0.7713
........................................Epoch: 62/200,  Loss: 0.7512
........................................Epoch: 62/200,  Loss: 0.7755
........................................Epoch: 62/200,  Loss: 0.7751
........................................Epoch: 62/200,  Loss: 0.7307
........................................Epoch: 62/200,  Loss: 0.7274
.............................           Epoch 62 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.1486 %
Confusion matrix
[[197   0   3   7   3  13  29  38   0   1]
 [  0 242  27   3   2   0   0   0   2  14]
 [  4   4 222   6   1   1   2   2   0  49]
 [ 26   3  48 129   3   5  30  21   4  21]
 [  3   0   1   1 253  12   0   1  15   4]
 [ 20   0   6   0  16 136  22  76  10   4]
 [ 47   0   0   8   0   3 207  25   0   0]
 [ 29   1   4   4   5  24  30 186   5   1]
 [  2   1   0   0  16  27   1   7 231   5]
 [  3  11  60   6   1   1   2   3   0 203]]
........................................Epoch: 63/200,  Loss: 0.7477
........................................Epoch: 63/200,  Loss: 0.7941
........................................Epoch: 63/200,  Loss: 0.7935
........................................Epoch: 63/200,  Loss: 0.7640
........................................Epoch: 63/200,  Loss: 0.7725
........................................Epoch: 63/200,  Loss: 0.7746
.............................           Epoch 63 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 66.7356 %
Confusion matrix
[[209   0   0   4   7  16  31  23   1   0]
 [  0 261   6   6   2   0   0   3   5   7]
 [  6  15 136  23   6  10   9  11   3  72]
 [ 39   3   8 114   6  15  34  33  18  20]
 [  3   0   0   1 272   8   0   0   6   0]
 [ 24   0   0   0  34 138  14  50  28   2]
 [ 55   0   0   3   0  10 194  27   0   1]
 [ 39   1   0   1   8  43  22 170   4   1]
 [  2   1   0   0  21  16   0   6 242   2]
 [  5  21  15  16  12   7   4  10   0 200]]
........................................Epoch: 64/200,  Loss: 0.7397
........................................Epoch: 64/200,  Loss: 0.7428
........................................Epoch: 64/200,  Loss: 0.7207
........................................Epoch: 64/200,  Loss: 0.7926
........................................Epoch: 64/200,  Loss: 0.7295
........................................Epoch: 64/200,  Loss: 0.7687
.............................           Epoch 64 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.4243 %
Confusion matrix
[[220   0   0  20   1   7  23  19   0   1]
 [  0 260  14   4   0   0   0   0   2  10]
 [  3   5 184  47   1   3   1   1   3  43]
 [ 22   3  15 209   1   7  11  11   2   9]
 [  1   1   1   9 224  19   0   1  29   5]
 [ 35   0   2  12   6 148  11  47  26   3]
 [ 71   0   0  21   0   3 178  17   0   0]
 [ 41   1   2  28   2  41  14 155   5   0]
 [  3   2   0   4   9  20   2   4 244   2]
 [  3  19  37  30   1   4   2   2   0 192]]
........................................Epoch: 65/200,  Loss: 0.7553
........................................Epoch: 65/200,  Loss: 0.7642
........................................Epoch: 65/200,  Loss: 0.7776
........................................Epoch: 65/200,  Loss: 0.8055
........................................Epoch: 65/200,  Loss: 0.7804
........................................Epoch: 65/200,  Loss: 0.7665
.............................           Epoch 65 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.6660 %
Confusion matrix
[[222   0   4   8   5  31   2  17   1   1]
 [  0 268   8   3   0   0   0   0   2   9]
 [  3  13 203  14   2   6   1   2   4  43]
 [ 37   7  28 142   6  11   6  22  14  17]
 [  1   0   3   1 260  10   0   1  13   1]
 [ 21   0   2   2  25 188   6  29  15   2]
 [103   0   1  15   0  14 122  31   3   1]
 [ 35   3   1   7   8  76   3 144   7   5]
 [  2   1   0   0  18  23   0   2 243   1]
 [  2  25  41  12   2   5   1   2   0 200]]
........................................Epoch: 66/200,  Loss: 0.7365
........................................Epoch: 66/200,  Loss: 0.7708
........................................Epoch: 66/200,  Loss: 0.7544
........................................Epoch: 66/200,  Loss: 0.7542
........................................Epoch: 66/200,  Loss: 0.7811
........................................Epoch: 66/200,  Loss: 0.7049
.............................           Epoch 66 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.2520 %
Confusion matrix
[[148   0   1   6   8  14  64  46   3   1]
 [  0 259  15   2   2   0   2   3   2   5]
 [  4   8 182  26   1   3   7   6   4  50]
 [ 21   5  17 150   5  13  34  27   7  11]
 [  2   0   0   2 263  11   0   1  10   1]
 [ 13   0   2   3  30 146  17  52  25   2]
 [ 22   0   0   3   0   9 228  27   0   1]
 [ 17   1   1   5  10  36  28 185   5   1]
 [  2   1   0   1  17  16   2   4 245   2]
 [  2  24  32  12   3   4   3   7   0 203]]
........................................Epoch: 67/200,  Loss: 0.7665
........................................Epoch: 67/200,  Loss: 0.7248
........................................Epoch: 67/200,  Loss: 0.7164
........................................Epoch: 67/200,  Loss: 0.7237
........................................Epoch: 67/200,  Loss: 0.7462
........................................Epoch: 67/200,  Loss: 0.7970
.............................           Epoch 67 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.7694 %
Confusion matrix
[[208   0   2   5   5  31  21  18   1   0]
 [  0 249  25   3   1   0   1   2   3   6]
 [  6   5 207  16   2   6   3   3   3  40]
 [ 44   5  26 128   7  16  26  23   6   9]
 [  3   0   0   0 266  12   0   1   8   0]
 [ 17   0   2   1  30 182   6  31  19   2]
 [ 58   0   0   2   0  32 179  18   0   1]
 [ 31   1   2   3   9  75  11 150   6   1]
 [  2   1   0   1  24  20   3   6 232   1]
 [  6  21  40  13   3   6   3   4   0 194]]
........................................Epoch: 68/200,  Loss: 0.7438
........................................Epoch: 68/200,  Loss: 0.7870
........................................Epoch: 68/200,  Loss: 0.7292
........................................Epoch: 68/200,  Loss: 0.7380
........................................Epoch: 68/200,  Loss: 0.7737
........................................Epoch: 68/200,  Loss: 0.7562
.............................           Epoch 68 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 67.7353 %
Confusion matrix
[[229   0   0   6   4  10  28  13   1   0]
 [  0 262  17   1   2   0   0   1   4   3]
 [ 12   8 212  23   4   3   8   3   4  14]
 [ 50   5  25 119   6  11  32  18  15   9]
 [  2   0   0   1 265  11   0   1  10   0]
 [ 35   0   2   2  23 141  20  45  20   2]
 [ 72   0   0   4   0   3 197  13   0   1]
 [ 63   1   1   1   8  32  29 148   6   0]
 [  2   1   0   1  15  23   0   4 243   1]
 [  8  29  72  13   7   4   3   5   0 149]]
........................................Epoch: 69/200,  Loss: 0.7107
........................................Epoch: 69/200,  Loss: 0.7567
........................................Epoch: 69/200,  Loss: 0.7904
........................................Epoch: 69/200,  Loss: 0.7824
........................................Epoch: 69/200,  Loss: 0.8033
........................................Epoch: 69/200,  Loss: 0.7657
.............................           Epoch 69 completed
----------------------------------------
----------------------------------------
-----------
Accuracy: 69.2865 %
Confusion matrix
[[197   0   1  11   4  12  30  34   2   0]
 [  0 257  17   6   0   0   0   1   2   7]
 [  4   6 196  21   3   4   3   6   2  46]
 [ 32   6  29 136   5   8  26  17  12  19]
 [  2   0   2   1 260   7   0   3  14   1]
 [ 19   0   2   1  24 125  16  71  30   2]
 [ 54   0   0   4   0   3 197  28   3   1]
 [ 30   2   1   5  10  28  14 191   7   1]
 [  2   2   0   1  18   9   0   5 253   0]
 [  2  25  35  17   4   5   2   2   0 198]]
No improvement for 10 epochs

Evaluation

The best fitting model has been saved as checkpoint. Load it and check the accuracy against the test data set.

In [25]:
# To avoid disk wear the checkpoints have been saved in the /tmp directory
# which hopefully is a RAM disk. Copy the current checkpoint to our directory.
os.popen("cp /tmp/checkpoint.pt checkpoint.pt 2>&1 && echo ok").read()
Out[25]:
'ok\n'
In [26]:
def load_checkpoint(path='checkpoint.pt'):
    """Reload model from checkpoint
    """
    checkpoint = torch.load(path)
    model = checkpoint['model']
    return model
In [27]:
# Check the accuary using the test data
model  = load_checkpoint('checkpoint.pt')
class_to_idx = model.class_to_idx
check_accuracy(model, testloader)
pass
----------------------------------------
----------------------------------------
-----------
Accuracy: 68.9786 %
Confusion matrix
[[215   0   0   3   1  17  30  17   6   1]
 [  0 256   2   4   1   1   1   1   3  21]
 [  6  15 153  33   1   9   0   1   3  68]
 [ 32   6  17 171   4  18  11  12   4  15]
 [  0   1   0   1 252  21   0   5   9   1]
 [ 25   1   1   3  26 165  15  29  22   3]
 [ 51   0   0   7   0  16 197  19   0   0]
 [ 35   0   1   8  10  63  19 146   6   1]
 [  3   1   0   3  20  26   1   4 228   4]
 [  3  10  29  18   3   6   0   4   1 216]]

The columns in the confusion matrix correspond to the predicted categories. The rows to the actual categories. Find the labels for the rows an columns below.

So a the noise inside a bus is easily recognized. But the sound of a street with pedestrians is easily mistake for a public square.

In [28]:
class_to_idx
Out[28]:
{'airport': 0,
 'bus': 1,
 'metro': 2,
 'metro_station': 3,
 'park': 4,
 'public_square': 5,
 'shopping_mall': 6,
 'street_pedestrian': 7,
 'street_traffic': 8,
 'tram': 9}

Prediction

Let's use the model to make a prediction

In [29]:
class Predict:
    """Image classifier"""

    def __init__(self):
        """Constructor"""
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        self.image = None
        self.category_names = None
        self.top_k = 5

    def classify(self, image_file_name, checkpoint_file_name,
                 category_names_file_name = None):
        """classify an image"""
        self.load_checkpoint(checkpoint_file_name)
        self.load_image(image_file_name)
        if category_names_file_name is not None:
            self.load_category_names(category_names_file_name)
        probs, categories = self.infer(self.top_k)
        self.output(probs, categories)
        self.draw_prediction(probs, categories)

    def infer(self, top_k):
        """Infer the classes"""
        self.model.to(self.device)
        self.model.eval()
        inputs = torch.stack((self.image,))
        inputs = inputs.to(self.device)

        with torch.no_grad():
            outputs = self.model(inputs)

        outputs = outputs.to("cpu")
        probs, indices = outputs.topk(top_k)
        probs = probs.exp()
        probs = probs.tolist()[0]
        indices = indices.tolist()[0]
        categories = [self.idx_to_class[index] for index in indices]
        return probs, categories

    def load_checkpoint(self, checkpoint_file_name):
        """Load checkpoint from file"""
        checkpoint = torch.load(checkpoint_file_name, map_location={'cuda:0': 'cpu'})
        self.model = checkpoint['model']
        self.criterion = nn.NLLLoss()
        class_to_idx = self.model.class_to_idx
        self.idx_to_class = {value : key
                             for key, value in class_to_idx.items()}

    def load_image(self, image_file_name):
        """Load image from file"""
        self.image = Image.open(image_file_name).convert('RGB')
        self.image = self.normalize_image(self.image)

    def normalize_image(self, image):
        """Normalize image"""
        return test_transforms(image)

    def output(self, probs, categories):
        """Output category names and propabilities"""
        if self.category_names is not None:
            categories = [self.category_names[category]
                          for category in categories]
            category_title = 'Category Name'
        else:
            category_title = 'Category'
        max_len = max([len(category) for category in categories])
        max_len = max(max_len, len(category_title))
        print('{:>{}} | {}'.format(category_title, max_len, 'Propability'))
        print('{:>{}}-+-{}'.format('-' * max_len, max_len, '-----------'))
        for i in range(len(probs)):
            print('{:>{}} | {:.4f}'.format( categories[i], max_len, probs[i]))

    def draw_prediction(self, propabilities, categories,
                        true_category = '', title = 'Prediction'):

        fig, plot = plt.subplots(nrows=1, ncols=1, figsize=(7,5))
        fig.tight_layout()
        fig.suptitle(title, fontsize=20, y=1.05)

        margin = 0.05
        n_cat = len(categories)
        ind = np.arange(n_cat)
        width = (1. - 2. * margin) / n_cat
    
        plot.barh(ind, propabilities[::-1], height = .8)
        plot.set_yticks(ind + margin)
        plot.set_yticklabels(categories[::-1], fontsize=16)
        plot.set_xlabel('propability')
            
    def set_device(self, device_name):
        """Set the cuda device"""
        self.device = torch.device(device_name)

    def set_top_k(self, top_k):
        """Set number of categories to output"""
        self.top_k = top_k
        
In [30]:
# Can you identify the sound?
x = readAudioFile(rawDataPath + 'bus-milan-1115-42136-a.wav')
ipd.Audio(x, rate=sr)
Out[30]:
In [31]:
# Check yout guess against the prediction.
predict = Predict()
predict.classify('data/spectrograms/bus/milan/1115-42136-a.png', 'checkpoint.pt', None)
      Category | Propability
---------------+------------
           bus | 0.7074
         metro | 0.2347
 metro_station | 0.0520
 shopping_mall | 0.0058
street_traffic | 0.0000

Deployment

The project folders contains two standalone Python programs.

  • train.py can be used to retrain the model on a new data set.
  • predict.py uses a saved checkpoint for predictions. Similar code could be used to create a web service for classification.

Conclusion

A workflow for classifying ambiant sound was demonstrated:

  • correcting sound quality by using a pre-emphasis filter
  • convert sound files to spectrograms
  • split the dataset into training, validation, and testing data
  • train a convolutional neural network using data augmentation
  • use the trained network for prediction

Though a network was used that is not specificically built for this classification task respectable accuracy rates were be achieved.

Directions for further investigation could be

  • a grid search to optimize the parameters of the augmentation transforms
  • testing further augmentation techniques like adding noise
  • design of a more specific neural network.